package com.sz.biz.logistics.core.service.impl;

import com.sz.biz.common.AbstractVersionEntityService;
import com.sz.biz.common.approval.ApprovalService;
import com.sz.biz.common.approval.ApprovalStatus;
import com.sz.biz.common.base.dto.AreaDto;
import com.sz.biz.common.base.entity.Country;
import com.sz.biz.common.base.service.AreaManager;
import com.sz.biz.common.base.service.AreaService;
import com.sz.biz.common.constants.CommCodes;
import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.common.sup.dto.SupplierDto;
import com.sz.biz.common.sup.service.SupplierService;
import com.sz.biz.logistics.base.dto.FlightDetailDto;
import com.sz.biz.logistics.base.dto.FlightDto;
import com.sz.biz.logistics.base.dto.ShippingLineSettingDto;
import com.sz.biz.logistics.base.entity.*;
import com.sz.biz.logistics.base.service.*;
import com.sz.biz.logistics.constants.ServiceConstants;
import com.sz.biz.logistics.constants.SubServiceTypes;
import com.sz.biz.logistics.constants.TopServiceTypes;
import com.sz.biz.logistics.core.dto.ServiceDto;
import com.sz.biz.logistics.core.dto.ServiceRegionDto;
import com.sz.biz.logistics.core.dto.ServiceRegionObjDto;
import com.sz.biz.logistics.core.entity.*;
import com.sz.biz.logistics.core.service.*;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.CommonModel;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.entity.VersionEntityBase;
import com.sz.common.base.exception.CommonErrorCodes;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.utils.DateUtils;
import com.sz.common.base.utils.EntityUtils;
import com.sz.common.base.utils.StringUtils;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.entity.SysDict;
import com.sz.common.core.system.service.SysDictService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Function: 服务的service. <br>
 * Date: 2017年02月15日 17:24 <br>
 * Author: wentao.chang
 */
@org.springframework.stereotype.Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class ServiceServiceImpl extends AbstractVersionEntityService implements ServiceService {

    private static final String MAINLINEOTHER = "MAINLINEOTHER";
    @Autowired
    private ServiceClassRelService serviceClassRelService;
    @Autowired
    private ServiceRegionRelService serviceRegionRelService;

    @Autowired
    private ServiceTypeRelService serviceTypeRelService;

    @Autowired
    private SysDictService dictService;

    @Autowired
    private ServiceCargoTypeRelService cargoTypeRelService;

    @Autowired
    private SupplierService supplierService;

    @Autowired
    private ApprovalService approvalService;

    @Autowired
    private ProductServiceRelService productServiceRelServicer;

    @Autowired
    private AirlineService airlineService;

    @Autowired
    private ShippingLineService shippingLineService;

    @Autowired
    private FlightService flightService;
    @Autowired
    private ProductService productService;
    @Autowired
    private ProductGroupService productGroupService;

    @Autowired
    private ShippingLineSettingService shippingLineSettingService;

    @Autowired
    private RegionSchemaService regionSchemaService;

    @Autowired
    private RegionService regionService;

    @Autowired
    private RegionItemService regionItemService;


    @Autowired
    private AreaManager areaManager;

    /**
     * 新增
     *
     * @param service 新增的实体
     * @return String uid
     */
    @Override
    public String save(ServiceDto service) throws ParseException {
        checkMainValid(service);
        //checkNameExist(null, service);
        checkCodeExist(null, service);
        service.setStatus(1);//1草稿 2提交 3 审核
        super.save(service);
        saveServiceTypes(service.getId(), service);//保存服务的类型
        saveCargoTypes(service.getId(), service.getCargoTypes());//保存货物类型
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_SERVICE", service);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SERVICE, UserActions.ADD, "新增服务", dataBackup);
        return service.getUid();
    }

    /**
     * 修改
     *
     * @param uid         uid
     * @param serviceDto  修改的对象
     * @param isFromAudit 是否来自审核
     * @return String
     */
    @Override
    public String update(String uid, ServiceDto serviceDto, boolean isFromAudit) throws ParseException {
        checkMainValid(serviceDto);
        checkCodeExist(uid, serviceDto);
        Service service = findActivedByUid(uid);
        if (service.getStatus().compareTo(ServiceConstants.Status.AUDIT_PASS ) == 0 && !isFromAudit) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_HAS_AUDITED, service.getId());
        }
        if (service.getStatus().compareTo(ServiceConstants.Status.AUDIT_PASS ) == 0 &&
                service.getIsOnline() != null && service.getIsOnline()) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_HAS_ONLINEED, service.getId());
        }
        if (service.getStatus().compareTo(ServiceConstants.Status.PENDING_AUDIT) == 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_HAS_SUBMITTED, service.getId());
        }

        //---新资料
        if (!isFromAudit) {
            service.setCode(serviceDto.getCode());
        }
        service.setName(serviceDto.getName());
        service.setCode(serviceDto.getCode());
        service.setDescription(serviceDto.getDescription());
        service.setLastUpdateUserId(PrincipalUtils.getAccountId());
        service.setSupplierId(serviceDto.getSupplierId());
        service.setServiceContent(serviceDto.getServiceContent());
        service.setDescription(serviceDto.getDescription());
        //五个新字段
        service.setEstimatedTime(serviceDto.getEstimatedTime());
        service.setEstimatedUnit(serviceDto.getEstimatedUnit());
        service.setWeightLimitMin(serviceDto.getWeightLimitMin());
        service.setWeightLimitMax(serviceDto.getWeightLimitMax());
        service.setWeightLimitUnitCode(serviceDto.getWeightLimitUnitCode());
        dao.update("ServiceMapper.update", service);


        List<ServiceTypeRel> sts = serviceTypeRelService.findByRefId(service.getId());
        String newType = serviceDto.getServiceTypeCodes().get(0);
        String oldType = sts.get(0).getServiceTypeCode();

        if (TopServiceTypes.MAINLINE.equalsIgnoreCase(newType) && TopServiceTypes.MAINLINE.equalsIgnoreCase(oldType) &&
                !serviceDto.getSubServiceTypeCode().equals(sts.get(0).getSubServiceTypeCode())) {
            if (!MAINLINEOTHER.equalsIgnoreCase(sts.get(0).getSubServiceTypeCode())) {
                serviceClassRelService.deleteByServiceId(service.getId());
                serviceRegionRelService.deleteByServiceId(service.getId());
            } else {
                serviceClassRelService.deleteByServiceId(service.getId());
            }
        }

        if (TopServiceTypes.MAINLINE.equalsIgnoreCase(newType) && !TopServiceTypes.MAINLINE.equalsIgnoreCase(oldType)) {
            if (!MAINLINEOTHER.equalsIgnoreCase(serviceDto.getSubServiceTypeCode())) {
                serviceClassRelService.deleteByServiceId(service.getId());
                serviceRegionRelService.deleteByServiceId(service.getId());
            }
        }

        if (!TopServiceTypes.MAINLINE.equalsIgnoreCase(newType) && TopServiceTypes.MAINLINE.equalsIgnoreCase(oldType)) {
            if (!MAINLINEOTHER.equalsIgnoreCase(sts.get(0).getSubServiceTypeCode())) {
                serviceClassRelService.deleteByServiceId(service.getId());
                serviceRegionRelService.deleteByServiceId(service.getId());
            }
        }

        saveServiceTypes(service.getId(), serviceDto);
        saveCargoTypes(service.getId(), serviceDto.getCargoTypes());

        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_SERVICE", service);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SERVICE, UserActions.UPDATE, "修改服务", dataBackup);

        return uid;
    }

    private void saveServiceTypes(Integer serviceId, ServiceDto service) {
        //先删除
        serviceTypeRelService.deleteByServiceId(serviceId);
        //在新增
        List<ServiceTypeRel> stypeRels = new ArrayList<>();
        for (String serviceTypeCode : service.getServiceTypeCodes()) {
            if (serviceTypeCode == null) {
                continue;
            }
            ServiceTypeRel rel = new ServiceTypeRel();
            rel.setServiceId(serviceId);
            rel.setServiceTypeCode(serviceTypeCode);
            rel.setSubServiceTypeCode(service.getSubServiceTypeCode());
            stypeRels.add(rel);
        }
        if (stypeRels.size() > 0) {
            serviceTypeRelService.save(stypeRels);
        }
    }

    /**
     * 保存服务的货物类型
     *
     * @param serviceId  服务的id
     * @param cargoCodes 货物类型集合
     */
    private void saveCargoTypes(Integer serviceId, List<String> cargoCodes) {
        //先删除
        cargoTypeRelService.deleteByServiceId(serviceId);
        //在新增
        if (!CollectionUtils.isEmpty(cargoCodes)) {
            List<ServiceCargoTypeRel> cargos = new ArrayList<>();
            for (String cargoCode : cargoCodes) {
                ServiceCargoTypeRel cargo = new ServiceCargoTypeRel();
                cargo.setCargoTypeCode(cargoCode);
                cargo.setServiceId(serviceId);
                cargos.add(cargo);
            }
            cargoTypeRelService.save(cargos);
        }
    }


    private void checkMainValid(ServiceDto service) {
        if (CollectionUtils.isEmpty(service.getServiceTypeCodes())) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "serviceTypeCodes");
        }
        if (CollectionUtils.isEmpty(service.getCargoTypes())) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "cargoTypes");
        }
        service.setName(getCheckedTrimString(service.getName(), "name"));
        service.setCode(getCheckedTrimString(service.getCode(), "code"));
        if (service.getSupplierId() == null || service.getSupplierId().compareTo(0) == 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "supplierId");
        }
        if (TopServiceTypes.MAINLINE.equals(service.getServiceTypeCodes().get(0)) && StringUtils.isEmpty(service.getSubServiceTypeCode())) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL, "subServiceTypeCode");
        }
        service.setServiceContent(service.getServiceContent() == null ? null : service.getServiceContent().trim());
        service.setDescription(service.getDescription() == null ? null : service.getDescription().trim());
        if (!TopServiceTypes.MAINLINE.equals(service.getServiceTypeCodes().get(0))) {
            service.setSubServiceTypeCode(null);
        }
    }

    private void checkCodeExist(String uid, Service service) {
        Map<String, Object> map = new HashMap<>();
        map.put("uid", uid);
        map.put("code", service.getCode());
        List<Service> listName = dao.findForList("ServiceMapper.findByCode", map, Service.class);
        if (listName.size() > 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_CODE_EXIST, service.getCode());
        }
    }

    /**
     * 根据id删除实体
     *
     * @param id id
     */
    private void deleteById(int id, Date date) {
        Map<String, Object> param = new HashMap<>();
        param.put("lastUpdateUserId", PrincipalUtils.getAccountId());
        param.put("id", id);
        param.put("inactiveTime", date);
        dao.update("ServiceMapper.deleteById", param);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("DELETE_SERVICE", param);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SERVICE, UserActions.DELETE, "删除服务", dataBackup);
    }

    /**
     * 根据uid上线服务
     *
     * @param uids uids
     */
    @Override
    public void online(List<String> uids) throws ParseException {
        for (String uid : uids) {
            Service service = findDtoActivedByUid(uid);

            this.judgeRegion(service);
            //提交流程
            ApprovalStatus fromStatus;
            if (service.getIsOnline() == null) {
                fromStatus = ApprovalStatus.Approved;
            } else {
                fromStatus = ApprovalStatus.Offline;
            }
            approvalService.approval(ApprovalService.ENTITY_TYPE_SERVICE, uid,
                    fromStatus, ApprovalStatus.Online, "", PrincipalUtils.getAccountId());
            Map<String, Object> params = new HashMap<>();
            params.put("id", service.getId());
            params.put("lastUpdateUserId", PrincipalUtils.getAccountId());
            dao.update("ServiceMapper.online", params);
            //保存操作日志
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("UPDATE_SERVICE", params);
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SERVICE, UserActions.UPDATE, "启用服务", dataBackup);
        }
    }

    /**
     * 根据uid下线服务
     *
     * @param uids uids
     */
    @Override
    public void offline(List<String> uids, boolean isConfirmed) throws ParseException {
        //判断服务是否被上线的产品引用,如果是产品的必须服务不允许停用
        Map<String, List<String>> map = findOnlineProduct(uids);
        List<String> productRequiredNames = map.get("required");
        List<String> productOptionalNames = map.get("optional");
        if (productRequiredNames.size() > 0) {
            throw Exceptions.bizException(ErrorCodes.SERVICE_OFFLINE_FAILURE, productRequiredNames.toString());
        }
        if (productOptionalNames.size() > 0 && !isConfirmed) {
            throw Exceptions.bizException(ErrorCodes.SERVICE_OFFLINE_FAILURE_OPTIONAL, "");
        }
        Date date = dao.getDbDate();
        for (String uid : uids) {
            approvalService.approval(ApprovalService.ENTITY_TYPE_SERVICE, uid,
                    ApprovalStatus.Online, ApprovalStatus.Offline, "", PrincipalUtils.getAccountId());

            Service old = findDtoActivedByUid(uid);
            if (old.getIsOnline() != null && !old.getIsOnline()) {
                throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_HAS_OFFLINEED, old.getCode());
            }
            //将旧数据失效
            deleteById(old.getId(), date);
            Map<String, Object> params = new HashMap<>();
            params.put("id", old.getId());
            params.put("lastUpdateUserId", PrincipalUtils.getAccountId());
            dao.update("ServiceMapper.offline", params);
            //保存操作日志
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("UPDATE_SERVICE", params);
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SERVICE, UserActions.UPDATE, "停用服务", dataBackup);
            ServiceDto serviceNew = new ServiceDto();
            BeanUtils.copyProperties(old, serviceNew);
            serviceNew.setId(-1);
            serviceNew.setActiveTime(date);
            serviceNew.setIsOnline(false);
            serviceNew.setStatus(3);
            super.save(serviceNew);
            copyRegions(old.getId(), serviceNew.getId());
            copyServiceTypes(old.getId(), serviceNew.getId());
            copyServiceClasses(old.getId(), serviceNew.getId());
            copyCargoTypes(old.getId(), serviceNew.getId());
        }
    }


    /**
     * 提交服务
     *
     * @param uids uids
     */
    @Override
    public void submit(List<String> uids) throws ParseException {
        if (CollectionUtils.isEmpty(uids)) {
            return;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("array", uids);
        List<Service> services = dao.findForList("ServiceMapper.findActivedByUids", map, Service.class);
        List<String> uidssaved = new ArrayList<>();
        //提交流程
        services.stream()
                .filter(service -> service.getStatus().compareTo(1) == 0)
                .forEach(service -> {
                    this.judgeRegion(service);
                    uidssaved.add(service.getUid());
                    //提交流程
                    approvalService.approval(ApprovalService.ENTITY_TYPE_SERVICE, service.getUid(),
                            ApprovalStatus.Draft, ApprovalStatus.Submitted, "", PrincipalUtils.getAccountId());
                });
        if (CollectionUtils.isEmpty(uidssaved)) {
            return;
        }
        map = new HashMap<>();
        map.put("status", 2);
        map.put("uids", uidssaved);
        map.put("lastUpdateUserId", PrincipalUtils.getAccountId());
        map.put("isRejected", false);
        dao.update("ServiceMapper.updateStatus", map);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_SERVICE", map);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SERVICE, UserActions.UPDATE, "提交服务", dataBackup);
    }

    private void judgeRegion(Service service) {

       List<ServiceTypeRel>  typeRels =  serviceTypeRelService.findByRefId(service.getId());
       if(!CollectionUtils.isEmpty(typeRels)){
           for (ServiceTypeRel typeRel : typeRels) {
              if( SubServiceTypes.MAINLINE_AIR.equals(typeRel.getSubServiceTypeCode())||SubServiceTypes.MAINLINE_SHIP.equals(typeRel.getSubServiceTypeCode())){
                  return;
              }
           }
       }
        List<ServiceRegionRel> regionRelList = serviceRegionRelService.findByServiceId(service.getId());
        if (!com.sz.common.base.utils.CollectionUtils.isEmpty(regionRelList)) {
            for (ServiceRegionRel serviceRegionRel : regionRelList) {
                RegionSchema regionSchema = regionSchemaService.findEntryActivedByUid(serviceRegionRel.getSchemaUid());
                if (!ObjectUtils.isEmpty(regionSchema) && StringUtils.isEmpty(regionSchema.getItemDetail())) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_SERVICE_ONLINE_REGION_CHECK);
                }

            }
        }
    }


    /**
     * 打回服务
     *
     * @param uids uids
     */
    @Override
    public void reject(List<String> uids, String msg) {
        List<String> uidsSaved = new ArrayList<>();
        for (String uid : uids) {
            Service service = (Service) dao.findForObject("ServiceMapper.findActivedByUid", uid);
            if (service.getStatus().compareTo(2) == 0) {
                uidsSaved.add(uid);
                //审核日志
                approvalService.approval(ApprovalService.ENTITY_TYPE_SERVICE, uid,
                        ApprovalStatus.Submitted, ApprovalStatus.Draft, msg, PrincipalUtils.getAccountId());
            }
        }
        if (CollectionUtils.isEmpty(uidsSaved)) {
            return;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("status", 1);
        map.put("uids", uidsSaved);
        map.put("lastUpdateUserId", PrincipalUtils.getAccountId());
        map.put("isRejected", true);
        dao.update("ServiceMapper.updateStatus", map);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_SERVICE", map);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SERVICE, UserActions.UPDATE, "打回服务", dataBackup);
    }

    /**
     * 审核服务
     *
     * @param uids uids
     */
    @Override
    public void audit(List<String> uids, String msg) throws ParseException {
        if (CollectionUtils.isEmpty(uids)) {
            return;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("array", uids);
        List<Service> services = dao.findForList("ServiceMapper.findActivedByUids", map, Service.class);
        List<Integer> idsSaved = new ArrayList<>();
        //审核日志
        services.stream()
                .filter(service -> service.getStatus().compareTo(2) == 0)
                .forEach(service -> {
                    idsSaved.add(service.getId());
                    //审核日志
                    approvalService.approval(ApprovalService.ENTITY_TYPE_SERVICE, service.getUid(),
                            ApprovalStatus.Submitted, ApprovalStatus.Approved, msg, PrincipalUtils.getAccountId());
                });
        if (CollectionUtils.isEmpty(idsSaved)) {
            return;
        }
        for (Integer id : idsSaved) {
            Map<String, Object> params = new HashMap<>();
            params.put("id", id);
            params.put("lastUpdateUserId", PrincipalUtils.getAccountId());
            dao.update("ServiceMapper.audit", params);
            //保存操作日志
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("UPDATE_SERVICE", map);
            PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_SERVICE, UserActions.UPDATE, "审核服务", dataBackup);
        }
    }

    private void copyRegions(int refId, int newId) {
        List<ServiceRegionRel> sRegions = serviceRegionRelService.findByServiceId(refId);
        if (!CollectionUtils.isEmpty(sRegions)) {
            for (ServiceRegionRel region : sRegions) {
                region.setServiceId(newId);
                region.setId(null);
            }
            serviceRegionRelService.batchsave(sRegions);
        }
    }

    private void copyCargoTypes(int refId, int newId) {
        List<ServiceCargoTypeRel> sCargos = cargoTypeRelService.findByRefId(refId);
        if (!CollectionUtils.isEmpty(sCargos)) {
            for (ServiceCargoTypeRel area : sCargos) {
                area.setServiceId(newId);
                area.setId(null);
            }
            cargoTypeRelService.save(sCargos);
        }
    }

    private void copyServiceTypes(int refId, int newId) {
        List<ServiceTypeRel> sTypes = serviceTypeRelService.findByRefId(refId);
        if (!CollectionUtils.isEmpty(sTypes)) {
            for (ServiceTypeRel stype : sTypes) {
                stype.setServiceId(newId);
                stype.setId(null);
            }
            serviceTypeRelService.save(sTypes);
        }
    }

    private void copyServiceClasses(int refId, int newId) {
        List<ServiceClassRel> scs = serviceClassRelService.findByRefId(refId);
        if (!CollectionUtils.isEmpty(scs)) {
            for (ServiceClassRel stype : scs) {
                stype.setServiceId(newId);
                stype.setId(null);
            }
            serviceClassRelService.save(scs);
        }
    }

    /**
     * 根据uid删除实体
     *
     * @param uids uid集合
     */
    @Override
    public void batchdelete(List<String> uids) {
        if (CollectionUtils.isEmpty(uids)) {
            return;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("array", uids);
        List<Service> services = dao.findForList("ServiceMapper.findActivedByUids", map, Service.class);
        List<Integer> idsSaved = services.stream()
                .filter(service -> service.getStatus().compareTo(1) == 0)
                .map(VersionEntityBase::getId)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(idsSaved)) {
            throw Exceptions.bizException(CommonErrorCodes.ERROR_MODEL_NOT_SAVED);
        }
        Date date = dao.getDbDate();
        idsSaved.forEach(id -> deleteById(id, date));
    }


    /**
     * 根据主键Id查询单个实体
     *
     * @param id 主键id
     * @return 查询出来的实体对象
     */
    @Override
    public Service findById(Integer id) {
        Service service = (Service) dao.findForObject("ServiceMapper.findById", id);
        if (service == null) {
            return null;
        }
        return service;
    }

    @Autowired
    private AreaService areaService;

    /**
     * 根据uid查询可用生效的实体
     *
     * @param uid 主键id
     * @return 查询出来的实体对象
     */
    @Override
    public ServiceDto findDtoActivedByUid(String uid) {
        Service service = this.findActivedByUid(uid);
        if (service == null) {
            return null;
        }
        ServiceDto dto = new ServiceDto();
        BeanUtils.copyProperties(service, dto);

        List<SysDict> dictList = dictService.findByCatalog("biz.service.type");
        Map<String, SysDict> dictMapp = EntityUtils.getStringKeyMapFromBeans(dictList, "code");

        List<ServiceTypeRel> types = serviceTypeRelService.findByRefId(service.getId());
        SupplierDto sdto = supplierService.findById(service.getSupplierId());
        dto.setSupplierName(sdto.getName());
        dto.setSupplierCode(sdto.getCode());
        if (!CollectionUtils.isEmpty(types)) {
            ServiceTypeRel stype = types.get(0);
            dto.setSubServiceTypeCode(stype.getSubServiceTypeCode());
            dto.getServiceTypeCodes().add(stype.getServiceTypeCode());
            dto.setServiceTypeName(dictMapp.get(stype.getServiceTypeCode() + "").getName());
            if (TopServiceTypes.MAINLINE.equals(stype.getServiceTypeCode())) {
                if (stype.getLineId() != null && stype.getLineId() != 0) {
                    if (stype.getSubServiceTypeCode().equals(SubServiceTypes.MAINLINE_AIR)) {
                        Airline al = airlineService.findSimpleById(stype.getLineId());
                        dto.setLineName(al.getName());
                        dto.setLineCode(al.getCode());
                    }
                    if (stype.getSubServiceTypeCode().equals(SubServiceTypes.MAINLINE_SHIP)) {
                        ShippingLine sl = shippingLineService.findSimpleById(stype.getLineId());
                        dto.setLineName(sl.getName());
                        dto.setLineCode(sl.getCode());
                    }
                }
                List<ServiceClassRel> rels = serviceClassRelService.findByRefId(service.getId());
                List<Integer> classIds = EntityUtils.getIntPropListFromBeans(rels, "classId");
                if (!CollectionUtils.isEmpty(classIds)) {
                    if (stype.getSubServiceTypeCode().equals(SubServiceTypes.MAINLINE_AIR)) {
                        List<Flight> flights = flightService.findSimpleByIds(classIds);
                        List<String> flightNames = EntityUtils.getStringPropListFromBeans(flights, "code");
                        dto.setClassName(StringUtils.toCommaString(flightNames));
                    }
                    if (stype.getSubServiceTypeCode().equals(SubServiceTypes.MAINLINE_SHIP)) {
                        List<ShippingLineSetting> sss = shippingLineSettingService.findSimpleByIds(classIds);
                        List<String> ssNames = EntityUtils.getStringPropListFromBeans(sss, "code");
                        dto.setClassName(StringUtils.toCommaString(ssNames));
                    }
                    dto.setClassId(classIds);
                }
                if (stype.getLineId() != null) {
                    dto.setLineId(stype.getLineId());
                }
            }
        }
        List<SysDict> cargoList = dictService.findByCatalog("biz.cargo.type");
        Map<String, SysDict> cargoMapp = EntityUtils.getStringKeyMapFromBeans(cargoList, "code");
        List<ServiceCargoTypeRel> cargos = cargoTypeRelService.findByRefId(service.getId());
        if (!CollectionUtils.isEmpty(cargos)) {
            StringBuilder finalSb = new StringBuilder();
            for (ServiceCargoTypeRel cargo : cargos) {
                finalSb.append(cargoMapp.get(cargo.getCargoTypeCode()).getName()).append("，");
                dto.getCargoTypes().add(cargo.getCargoTypeCode());
            }
            dto.setCargoTypeName(finalSb.length() > 0 ? finalSb.substring(0, finalSb.length() - 1) : "");
        }

        dto.setStatusName(super.getStatusName(dto.getStatus(), dto.getIsOnline()));


        if (!StringUtils.isEmpty(service.getEstimatedUnit())) {
            Map<String, String> dictmp = dictService.findMapByCatalog("biz.product.estimated.unit");
            dto.setEstimatedUnitName(dictmp.get(service.getEstimatedUnit()));
        }
        return dto;

    }

    @Override
    public Service findActivedByUid(String uid) {
        Service service = null;
        if (StringUtils.hasLength(uid)) {
            service = (Service) dao.findForObject("ServiceMapper.findActivedByUid", uid);
        }
        return service;
    }

    /**
     * h获取服务的详细信息
     *
     * @param uid
     * @return
     */
    @Override
    public ServiceRegionObjDto findServiceRegionsByUid(String uid) {

        ServiceRegionObjDto regionDto = new ServiceRegionObjDto();
        Service service = this.findActivedByUid(uid);
        List<ServiceTypeRel> types = serviceTypeRelService.findByRefId(service.getId());
        if (!CollectionUtils.isEmpty(types)) {
            ServiceTypeRel stype = types.get(0);

            //空运
            if (SubServiceTypes.MAINLINE_AIR.equals(stype.getSubServiceTypeCode())) {
                List<ServiceClassRel> rels = serviceClassRelService.findByRefId(service.getId());
                List<Integer> ids = EntityUtils.getIntPropListFromBeans(rels, "classId");
                if (!CollectionUtils.isEmpty(ids)) {
                    //获取班次的详情
                    ids.forEach(id -> {
                        FlightDto dto = flightService.findById(id);
                        ServiceRegionDto srdto = new ServiceRegionDto();
                        srdto.setId(dto.getId());

                        List<FlightDetailDto> details = dto.getDetails();
                        if (!com.sz.common.base.utils.CollectionUtils.isEmpty(details)) {
                            dto.setStartTime(details.get(0).getStartTime());
                            if (details.size() >= 2) {
                                dto.setEndTime(details.get(details.size() - 1).getArriveTime());
                            }
                        }
                        srdto.setName((StringUtils.isEmpty(dto.getCode()) ? "" : dto.getCode()) + "(" +
                                (StringUtils.isEmpty(dto.getStartTime()) ? "" : dto.getStartTime()) + " - " +
                                (StringUtils.isEmpty(dto.getEndTime()) ? "" : dto.getEndTime()) + ")");
                        regionDto.getStarts().add(srdto);
                    });
                }
            }
            //海运
            else if (SubServiceTypes.MAINLINE_SHIP.equals(stype.getSubServiceTypeCode())) {
                List<ServiceClassRel> rels = serviceClassRelService.findByRefId(service.getId());
                List<Integer> ids = EntityUtils.getIntPropListFromBeans(rels, "classId");
                if (!CollectionUtils.isEmpty(ids)) {
                    //获取班次的详情
                    ids.forEach(id -> {
                        ShippingLineSettingDto dto = shippingLineSettingService.findById(id);
                        ServiceRegionDto srdto = new ServiceRegionDto();
                        srdto.setId(dto.getId());
                        srdto.setName((StringUtils.isEmpty(dto.getCode()) ? "" : dto.getCode()) + "(" + DateUtils.formatDetailDate(dto.getEta()) + " - "
                                + DateUtils.formatDetailDate(dto.getEtd()) + ")");
                        regionDto.getStarts().add(srdto);
                    });
                }
            } else if (SubServiceTypes.MAINLINE_OTHER.equals(stype.getSubServiceTypeCode())) {
                List<ServiceRegionRel> regionList = serviceRegionRelService.findByServiceId(service.getId());
                if (!CollectionUtils.isEmpty(regionList)) {
                    regionList.forEach(region -> {
                        RegionSchema schema = regionSchemaService.findEntryActivedByUid(region.getSchemaUid());
                        if (schema != null) {
                            List<Integer> regionIds = regionService.findIdBySchemaUid(schema.getUid());
                            if (!CollectionUtils.isEmpty(regionIds)) {
                                regionIds.forEach(regionid -> {
                                    List<RegionItem> items = regionItemService.findByRegionId(regionid);
                                    if (!CollectionUtils.isEmpty(items)) {
                                        items.forEach(item -> {
                                            //国家
                                            if (item.getType() == 1) {
                                                Country country = areaManager.findByCountryCode(item.getCountry());
                                                ServiceRegionDto srdto = new ServiceRegionDto();
                                                srdto.setId(item.getId());

                                                srdto.setName(country.getName() + "(" + item.getCountry() + ")");
                                                if (CommCodes.PRODUCT_SERVICE_REGION_START.equals(region.getType())) {
                                                    regionDto.getStarts().add(srdto);
                                                } else {
                                                    regionDto.getEnds().add(srdto);
                                                }
                                            }
                                            //国内外城市
                                            if (item.getType() == 2 || item.getType() == 3) {
                                                AreaDto ad = areaService.findByAreaId(item.getAreaId(), item.getCountry());
                                                ServiceRegionDto srdto = new ServiceRegionDto();
                                                srdto.setId(item.getId());
                                                srdto.setName(ad.getName() + "(" + item.getCountry() + ")");
                                                if (CommCodes.PRODUCT_SERVICE_REGION_START.equals(region.getType())) {
                                                    regionDto.getStarts().add(srdto);
                                                } else {
                                                    regionDto.getEnds().add(srdto);
                                                }
                                            }

                                        });

                                    }
                                });
                            }

                        }
                    });
                }
            }
            //其他
            else {
                List<ServiceRegionRel> regionList = serviceRegionRelService.findByServiceId(service.getId());
                if (!CollectionUtils.isEmpty(regionList)) {
                    regionList.forEach(region -> {
                        //只对起点控制
                        if (CommCodes.PRODUCT_SERVICE_REGION_START.equals(region.getType())) {
                            RegionSchema schema = regionSchemaService.findEntryActivedByUid(region.getSchemaUid());
                            if (schema != null) {
                                List<Integer> regionIds = regionService.findIdBySchemaUid(schema.getUid());
                                if (!CollectionUtils.isEmpty(regionIds)) {
                                    regionIds.forEach(regionid -> {
                                        List<RegionItem> items = regionItemService.findByRegionId(regionid);
                                        if (!CollectionUtils.isEmpty(items)) {
                                            items.forEach(item -> {
                                                //国家
                                                if (item.getType() == 1) {
                                                    Country country = areaManager.findByCountryCode(item.getCountry());
                                                    ServiceRegionDto srdto = new ServiceRegionDto();
                                                    srdto.setId(item.getId());
                                                    srdto.setName(country.getName() + "(" + item.getCountry() + ")");
                                                    regionDto.getStarts().add(srdto);
                                                }
                                                //国内外城市
                                                if (item.getType() == 2 || item.getType() == 3) {
                                                    AreaDto ad = areaService.findByAreaId(item.getAreaId(), item.getCountry());
                                                    ServiceRegionDto srdto = new ServiceRegionDto();
                                                    srdto.setId(item.getId());
                                                    srdto.setName(ad.getName() + "(" + item.getCountry() + ")");
                                                    regionDto.getStarts().add(srdto);
                                                }

                                            });

                                        }
                                    });
                                }

                            }
                        }
                    });
                }
            }
        }


        return regionDto;
    }

    /**
     * 判断服务是否在上线产品中引用
     *
     * @param uids uids
     * @return Map
     */
    private Map<String, List<String>> findOnlineProduct(List<String> uids) {
        Map<String, List<String>> map = new HashMap<>();
        List<String> productRequiredNames = new ArrayList<>();
        List<String> productOptionalNames = new ArrayList<>();
        //判断服务是否被上线的产品引用
        List<ProductServiceRel> onLineProductList = productServiceRelServicer.findOnlineProductByServiceUids(uids);
        if (null != onLineProductList && onLineProductList.size() > 0) {

            for (ProductServiceRel productServiceRel : onLineProductList) {
                //如果服务是主服务或者必选服务，不能下线； 可选服务提示
                if (ProductServicePropertyEnum.OPTIONAL.getCode().equalsIgnoreCase(productServiceRel.getServiceProperty().getCode())) {
                    productOptionalNames.add(productServiceRel.getProductName());
                } else {
                    productRequiredNames.add(productServiceRel.getProductName());
                }
            }
        }
        map.put("required", productRequiredNames);
        map.put("optional", productOptionalNames);

        return map;
    }


    /**
     * 获取uids生效的报价方案主要信息
     *
     * @param uids uids
     */
    @Override
    public List<Service> findActivedByUids(List<String> uids) {
        if (org.springframework.util.CollectionUtils.isEmpty(uids)) {
            return null;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("array", uids);
        return dao.findForList("ServiceMapper.findActivedByUids", map, Service.class);
    }

    @Override
    public Service findByUid(String uid, Boolean isDeleted) {
        Service service = null;
        if (!StringUtils.isEmpty(uid)) {
            List<Service> serviceList = this.findByUids(Arrays.asList(uid), isDeleted);
            if (!CollectionUtils.isEmpty(serviceList)) {
                service = serviceList.get(0);
            }
        }
        return service;
    }

    public List<Service> findByUids(List<String> uids, Boolean isDeleted) {
        List<Service> serviceList = null;
        if (!CollectionUtils.isEmpty(uids)) {
            ParamData pd = new ParamData();
            pd.put("uids", uids);
            pd.put("isDeleted", isDeleted);
            serviceList = dao.findForList("ServiceMapper.findByUids", pd, Service.class);
        }
        return serviceList;
    }


    /**
     * 根据uid查询可用生效的实体
     *
     * @param uid  uid
     * @param time 时间点
     * @return 查询出来的实体对象
     */
    @Override
    public ServiceDto findByUidAndTime(String uid, Date time) {
        Map<String, String> map = new HashMap<>();
        map.put("uid", uid);
        map.put("time", DateUtils.formatDetailDate(time));
        Service service = (Service) dao.findForObject("ServiceMapper.findByUidAndTime", map);
        if (service == null) {
            return null;
        }
        ServiceDto dto = new ServiceDto();
        BeanUtils.copyProperties(service, dto);
        return dto;
    }

    /**
     * 根据uids查询可用生效的实体
     *
     * @param uids uids
     * @param time 时间点
     * @return 查询出来的实体对象
     */
    @Override
    public List<Service> findByUidsAndTime(List<String> uids, Date time) {
        Map<String, Object> map = new HashMap<>();
        map.put("uids", uids);
        map.put("time", DateUtils.formatDetailDate(time));
        return dao.findForList("ServiceMapper.findByUidsAndTime", map, Service.class);
    }

    /**
     * 根据条件查询实体
     *
     * @param params 查询的参数集
     * @return 查询出的数据
     */
    @Override
    public QResultDto findByFilter(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);
        List<Service> services = dao.findForList("ServiceMapper.findByFilterListPage", pd, Service.class);

        List<SysDict> dictList = dictService.findByCatalog("biz.service.type");
        Map<String, SysDict> dictMapp = EntityUtils.getStringKeyMapFromBeans(dictList, "code");


        List<ServiceDto> sDtos = new ArrayList<>();
        for (Service service : services) {
            ServiceDto dto = new ServiceDto();
            BeanUtils.copyProperties(service, dto);

            List<ServiceTypeRel> types = serviceTypeRelService.findByRefId(service.getId());

            ServiceTypeRel stype = types.get(0);
            dto.setServiceTypeName(dictMapp.get(stype.getServiceTypeCode() + "").getName());
            dto.setStatusName(super.getStatusName(service.getStatus(), dto.getIsOnline()));
            dto.setSubServiceTypeCode(stype.getSubServiceTypeCode());

            sDtos.add(dto);
        }
        return new QResultDto(sDtos, pd.getPagination());
    }

    @Override
    public List<CommonModel> findActivedByServiceUidList(List<String> serviceUids) {
        List<CommonModel> commonModelList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(serviceUids)) {
            ParamData pd = new ParamData();
            pd.put("uids", serviceUids);
            commonModelList = dao.findForList(getSqlName("findActivedByServiceUidList"), pd, CommonModel.class);
        }
        return commonModelList;
    }

    /**
     * 异步校验服务名称
     *
     * @param uid  uid
     * @param name name
     */
    @Override
    public void nameCheck(String uid, String name) {
        Map<String, Object> map = new HashMap<>();
        map.put("uid", uid);
        map.put("name", name);
        List<Service> listName = dao.findForList("ServiceMapper.findByName", map, Service.class);
        if (listName.size() > 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_NAME_EXIST, name);
        }
    }

    /**
     * 异步校验服务编码
     *
     * @param uid  uid
     * @param code code
     */
    @Override
    public void codeCheck(String uid, String code) {
        Map<String, Object> map = new HashMap<>();
        map.put("uid", uid);
        map.put("code", code);
        List<Service> listCode = dao.findForList("ServiceMapper.findByCode", map, Service.class);
        if (listCode.size() > 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_CODE_EXIST, code);
        }
    }

    @Override
    protected String getMapperNamespace() {
        return "ServiceMapper";
    }
}
